package com.gitee.qdbp.base.controlling;

import java.lang.reflect.Field;
import org.springframework.util.ReflectionUtils;
import com.gitee.qdbp.able.beans.AcceptAttrs;
import com.gitee.qdbp.able.exception.ServiceException;
import com.gitee.qdbp.base.controlling.DataIsolationBaseControlling.Metadata.Target;
import com.gitee.qdbp.base.enums.OperateType;
import com.gitee.qdbp.tools.utils.VerifyTools;

/**
 * 根据数据隔离元数据获取AcceptAttrs进行隔离控制
 *
 * @author zhaohuihua
 * @version 170714
 */
public abstract class DataIsolationSimpleControlling extends DataIsolationBaseControlling {

    /** {@inheritDoc} **/
    @Override
    protected void handleDataIsolation(Metadata metadata, OperateType operateType) throws ServiceException {

        Object o = metadata.getObject();
        Class<?> clazz = o.getClass();
        String className = clazz.getName();

        for (String name : VerifyTools.nvl(metadata.getFields(), new String[0])) {
            Field valueField = ReflectionUtils.findField(clazz, name);
            if (valueField == null) {
                if (metadata.isStrict()) {
                    throw new IllegalStateException("Field " + name + " not found in " + className);
                } else {
                    continue;
                }
            }
            String dataType = ControllingTools.findTableName(clazz);
            AcceptAttrs<?> attrs = getAcceptAttrs(o, valueField, dataType, operateType);
            if (attrs == null) {
                return; // 返回null, 将不会执行任何后续处理
            }
            ReflectionUtils.makeAccessible(valueField);
            if (attrs.isStarts()) {
                // 判断是否存在xxxStarts方法
                Field startsField = ControllingTools.findStartsField(clazz, name);
                if (startsField != null) {
                    ReflectionUtils.makeAccessible(startsField);
                    ControllingTools.doCheckAndSetValue(o, valueField, startsField, attrs, operateType);
                } else {
                    ControllingTools.doCheckAndSetValue(o, valueField, attrs, operateType);
                }
            } else {
                ControllingTools.doCheckAndSetValue(o, valueField, attrs, operateType);
            }
        }

        for (Target target : VerifyTools.nvl(metadata.getTargets(), new Target[0])) {
            handleDataIsolation(target.getMetadata(), operateType); // 递归调用
        }
    }

    /**
     * 获取数据隔离的权限属性
     * 
     * @param object 数据对象
     * @param field 字段(tenantCode/deptCode之类)
     * @param dataType 数据类型(表名)
     * @param operateType 操作类型, 查询/新增/修改/删除
     * @return 权限属性, return null将不会执行任何后续处理
     * @throws ServiceException
     */
    protected abstract AcceptAttrs<?> getAcceptAttrs(Object object, Field field, String dataType,
            OperateType operateType) throws ServiceException;

}
